﻿ //
// BindablePasswordBox.cs
//
// Modified version of http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html
//
// Authors:
//    Claus Jørgensen <10229@iha.dk>
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace RSD.View.Assets
{
    public class BindablePasswordBox : Decorator
    {
        public static readonly DependencyProperty PasswordProperty;

        public static readonly DependencyProperty TabIndexProperty = 
            DependencyProperty.Register("TabIndex", 
                typeof(int), typeof(BindablePasswordBox),
                new FrameworkPropertyMetadata(0,
                        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                        new PropertyChangedCallback(OnTabIndexPropertyChanged)));

        private bool isPreventCallback;
        private RoutedEventHandler savedCallback;

        static BindablePasswordBox()
        {
            PasswordProperty = DependencyProperty.Register("Password",
                typeof(string), typeof(BindablePasswordBox),
                new FrameworkPropertyMetadata("",
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    new PropertyChangedCallback(OnPasswordPropertyChanged)));
        }

        public BindablePasswordBox()
        {
            savedCallback = HandlePasswordChanged;

            PasswordBox passwordBox = new PasswordBox();
            passwordBox.PasswordChanged += savedCallback;
            passwordBox.TabIndex = TabIndex;

            Child = passwordBox;
        }

        public int TabIndex
        {
            get
            {
                return (int)GetValue(TabIndexProperty);
            }
            set
            {
                SetValue(TabIndexProperty, value);
            }
        }

        public string Password
        {
            get
            {
                return GetValue(PasswordProperty) as string;
            }
            set
            {
                SetValue(PasswordProperty, value);
            }
        }

        private static void OnPasswordPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs eventArgs)
        {
            BindablePasswordBox bindablePasswordBox = (BindablePasswordBox)d;
            PasswordBox passwordBox = (PasswordBox)bindablePasswordBox.Child;

            if (bindablePasswordBox.isPreventCallback)
            {
                return;
            }

            passwordBox.PasswordChanged -= bindablePasswordBox.savedCallback;
            passwordBox.Password = (eventArgs.NewValue != null) ? eventArgs.NewValue.ToString() : "";
            passwordBox.PasswordChanged += bindablePasswordBox.savedCallback;
        }

        private static void OnTabIndexPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs eventArgs)
        {
            BindablePasswordBox bindablePasswordBox = (BindablePasswordBox)d;
            PasswordBox passwordBox = (PasswordBox)bindablePasswordBox.Child;

            if (bindablePasswordBox.isPreventCallback)
            {
                return;
            }

            passwordBox.TabIndex = (eventArgs.NewValue != null) ? (int)eventArgs.NewValue : 0; 
        }

        private void HandlePasswordChanged(object sender, RoutedEventArgs eventArgs)
        {
            PasswordBox passwordBox = (PasswordBox)sender;

            isPreventCallback = true;
            Password = passwordBox.Password;
            isPreventCallback = false;
        }
    }
}
